package portal.conf;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;

import beans.HttpConfig;
import portal.common.MyStringUtils;
import portal.conf.entity.BaseConf;
import portal.conf.entity.EtcHostsEntity;
import portal.conf.entity.GPUEntity;
import portal.conf.entity.QueueEntity;

public abstract class AbstractConf {
	protected final boolean IsDebug=HttpConfig.fake;
	protected Logger logger= LoggerFactory.getLogger(AbstractConf.class);
	protected static final int  CONF_COMMENT=0;
	protected static final int  CONF_CONCAT=1;
	protected static final int  CONF_DELETE=2;
	protected static final int  CONF_REPLACE_COMMENT=3;
	protected static final int  CONF_REPLACE=4;
	/*******
	 * 最近一次读取配置文件时，配置文件的修改时间（毫秒）
	 * 在Linux 下，默认精确到秒，在windows下精确到毫秒
	 * ******/
	protected long lastModified=-1; 
	/****
	 * 需要解析的配置文件的开始标记（单个配置实体而言）
	 * ****/
	protected  String startTitle="Begin Host";
	/****
	 * 需要解析的配置文件的结束标记（单个配置实体而言）
	 * ****/
	protected  String endTitle="End Host";
	/**
	 * 配置文件的存储路径
	 * **/
	protected  String fileName="//app//unischeduler//conf//hosts.conf";
	/****
	 * 解析后的配置信息存储的列表 采用Vector 为了保证线程安全
	 * ***/
	protected Vector<BaseConf> confList =new Vector<>();
	//private static long lastModified=-1;
	/****
	 * 新增配置
	 * @param fileName 需要操作的配置的文件名
	 * @param data 需要更新的数据，数组长度表示数据的长度
	 * *****/
	protected synchronized  void insertConf(String fileName,String[] data) {
		FileWriter fw = null;
		try {
			//如果文件存在，则追加内容；如果文件不存在，则创建文件
			File f=new File(fileName);
			fw = new FileWriter(f, true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		PrintWriter pw = new PrintWriter(fw);
		for(String ele:data){
			pw.println(ele);
		}
		pw.flush();
		try {
			fw.flush();
			pw.close();
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//selectAllConf(fileName)
	}
	/****
	 * 新增配置重载方法
	 * @param fileName 需要操作的配置的文件名
	 * @param data 需要更新的数据，数组长度表示数据的长度
	 * 抽象类中不必要存在
	protected  void insertConf(String fileName,String data){
		if(StringUtils.isEmpty(data))
			return;
		insertConf(fileName,data.split("\n"));
	}*/
	/****
	 * 检索配置文件中所有的配置信息，并以列表形式返回，执行前先校验上次读取时间
	 * @param fileName 需要解析的配置文件的存储位置
	 * @param clazz 将要解析成为的实体类型
	 * @return 返回解析到的配置列表
	 * ****/
	protected synchronized  List<BaseConf> selectAllConf(String fileName,Class<?> clazz){
	//public static synchronized void readFileByLines(String fileName) {
	    File file = new File(fileName);
	    if(!file.exists()|| file.lastModified()<= getLastModified())
	    	return getConfList();
	    //System.out.println("---------------");
	    return selectAllConf(file ,clazz);
	}
	protected synchronized  List<BaseConf> selectAllConf(Class<?> clazz){
		return selectAllConf(fileName,clazz);
	}
	/******
	 * 检索配置文件中所有的配置信息，不校验上次读取时间
	 * @param file 待读取的文件
	 * @param clazz   待解析成为的目标对象。
	 * @return 返回解析到的配置列表
	 * ******/
	protected List<BaseConf> selectAllConf(File file,Class<?> clazz){
		if(file==null || !file.exists() )
			return getConfList();
		setLastModified(file.lastModified());
	
		BufferedReader reader = null;
		try {
			//System.out.println("以行为单位读取文件内容，一次读一整行：");
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			int line = 0;
			BaseConf qe =null;//(BaseConf)t.newInstance() ;
			clearConfList();
			//qe=()
				// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				// 显示行号
				line++;
				tempString=MyStringUtils.trimAll(tempString);
				if(MyStringUtils.isEmpty(tempString)||tempString.startsWith("#"))continue;
				if(tempString.indexOf("#")>0){// 剔除掉行尾的注释性内容
					tempString=tempString.substring(0, tempString.indexOf("#"));
					//System.out.println(tempString);
					//System.out.println(tempString.indexOf("#"));
					}				
					//System.out.println(tempString);
					qe=(BaseConf) analysiConf(tempString,line,clazz,qe);				
		        }
				
		      reader.close();
	    } catch (IOException e) {
	      e.printStackTrace();
	    } finally {
	      if (reader != null){
	        try {
	            reader.close();
	        } catch (IOException e1) {
	            }
	        }
	    }
		return getConfList();
	}

	
	/******
	 * @deprecated 注释调文件中制定行，已废弃，请用 removeConf(BaseConf baseConf ,String fileName,int oper);代替
	 * ******/
	@Deprecated 
	protected void commentConf(BaseConf bConf,String fileName){
		File file = new File(fileName); //创建目标文件
		try {
			//long start = System.currentTimeMillis(); //开始时间
			BufferedReader br = new BufferedReader(
			        						new InputStreamReader (
			        									new FileInputStream( file))); //创建对目标文件读取流
			File newFile = new File(fileName+".tmp"); //创建临时文件
			if (!newFile.exists()){
				newFile.createNewFile(); //不存在则创建
         }//   OutputStreamWriter
            //创建对临时文件输出流，并追加
			BufferedWriter bw = new BufferedWriter(
			        new OutputStreamWriter(
			                new FileOutputStream(newFile,true)));
			String string = null; //存储对目标文件读取的内容
			int line = 0; //替换次数
			while ((string = br.readLine()) != null){
			   line++;
			   	/****
			   	 * 注释调原有的配置信息	 * 
			   	 * ***/
			   if(line>=bConf.getLineStart() && line<= bConf.getLineEnd())
				   string ="#"+string;
			   bw.write(string); 
			   bw.newLine(); //添加换行
			}
			br.close(); //关闭流，对文件进行删除等操作需先关闭文件流操作
			bw.close();
			String filePath = file.getCanonicalPath();
			file.delete(); //删除源文件
			newFile.renameTo(new File(filePath)); //将新文件更名为源文件
			/**********************************
			 * 此时必须更新List conf * 
			 * ********************************/
			//ListQueueConf.readFileByLines(fileName);

      } catch(IOException e){
         e.printStackTrace();//System.out.println(e.getMessage());
      }catch(Exception e){
        	e.printStackTrace();
        }
	}
	protected boolean removeConf(BaseConf bConf){
		return removeConfC(bConf,fileName);
	}
	/******
	 * 通过注释方式移除配置信息
	 * ****/
	protected boolean removeConfC(BaseConf bConf,String fileName){
		if(bConf==null)return false;
		updateFile(bConf,fileName,CONF_COMMENT);
		bConf.setLineEnd(-1);
		bConf.setLineStart(-1);
		return true;
	}
	/******
	 * 通过删除方式移除配置信息
	 * ****/
	protected boolean removeConfD(BaseConf bConf,String fileName){
		if(bConf==null) return false;
		updateFile(bConf,fileName,CONF_DELETE);
		return true;
	}
	/**************************************************************************************************
	*更新Conf 文件操作 
	*@param bConf baseConf对象，记录要更改的信息的行信息。
	*@param fileName  .conf 文件的具体路径
	*@param oper  对配置信息的执行操作（	0：注释，
	*											1：追加BaseConf的toString 数据，
	*											2：删除该条配置，而非采用注释方式,
	*											3：替换原有行,并将元有内容以注释方式删除）
	***************************************************************************************************/
	protected synchronized  void updateFile(BaseConf bConf,String fileName,int oper){
		if(bConf==null)return;
		File file = new File(fileName); //创建目标文件
		try {
			//long start = System.currentTimeMillis(); //开始时间
			BufferedReader br = new BufferedReader(
			        						new InputStreamReader (
			        									new FileInputStream( file))); //创建对目标文件读取流
			File newFile = new File(fileName+".tmp"); //创建临时文件
			if (!newFile.exists()){
				newFile.createNewFile(); //不存在则创建
         }//   OutputStreamWriter
            //创建对临时文件输出流，并追加
			BufferedWriter bw = new BufferedWriter(
			        new OutputStreamWriter(
			                new FileOutputStream(newFile,true)));
			String string = null; //存储对目标文件读取的内容
			int line = 0; //行数
			//System.out.println(bConf.getLineStart());
			while ((string = br.readLine()) != null){
			   line++;
			   	/****
			   	 * 注释调原有的配置信息	 * 
			   	 * ***/
			   if(line>=bConf.getLineStart() && line<= bConf.getLineEnd()){
					switch(oper){
						default:
				  		case CONF_COMMENT:{//注释调原有的内容
				  				string ="#"+string;
				  		}break;
				  		case CONF_CONCAT:{//在该行后追加（仅限hosts.conf）
				  			bw.write(string); 
							bw.newLine();
							string=bConf.toString();
				  		}break;	
				  		case CONF_DELETE:{//跳过该行，不保存到新文件
				  			continue;
				  		}
				  		case CONF_REPLACE_COMMENT:{//注释并替换原有行,此操作仅限值 Conf实体为单行
				  			string ="#"+string;
				  			bw.write(string); 
							bw.newLine();							
				  		}//此处无需break,，需要继续执行CONF_REPLACE 内容
				  		case CONF_REPLACE:;
				  			string =bConf.toString();
				  		break;
					}
				}
			   //System.out.println(string);
			   bw.write(string); 
			   bw.newLine(); //添加换行
			}
			br.close(); //关闭流，对文件进行删除等操作需先关闭文件流操作
			bw.close();
			String filePath = file.getCanonicalPath();
			file.delete(); //删除源文件
			newFile.renameTo(new File(filePath)); //将新文件更名为源文件		

      } catch(IOException e){
         e.printStackTrace();//System.out.println(e.getMessage());
      }catch(Exception e){
        	e.printStackTrace();
        }
	}
	/****
	 * 清除读取到的配置列表
	 * ****/
	protected void clearConfList() {
		// TODO Auto-generated method stub
		if(confList==null)
			confList=new Vector<>();
		//if(confList)
		confList.clear();
	}
	/***
	 * 把配置对象添加到配置列表
	 * @param obj
	 * ***/
	protected boolean addToConfList(BaseConf obj) {
		// TODO Auto-generated method stub
		if(confList==null)
			confList=new Vector<>();
		if(isEntityExist((BaseConf)obj))
			return false;
		confList.add(obj);
		//System.out.println("add to conf");
		return false;
	}
	/****
	 * 获取配置列表对象 
	 * @return 返回配置列表对象
	 *****/
	protected List<BaseConf> getConfList() {
		// TODO Auto-generated method stub
		if(confList==null)
			confList=new Vector<>();
		return confList;
	}

	protected long getLastModified() {
		// TODO Auto-generated method stub
		return lastModified;
	}

	protected void setLastModified(long modified) {
		// TODO Auto-generated method stub
		lastModified=modified;
	}
	public void setFileName(String fname) {  
		fileName=fname;
	} 
	public void setEndTitle(String fname) {  
		endTitle=fname;  
	}
	public void setStartTitle(String fname) {  
		startTitle=fname; 
	} 
	public String getFileName(){
		return fileName;
	}
	/*****
	 * 抽象方法，读取配置文件时解析策略。需要子类实现具体的解析策略。
	 * @param tempString
	 * @param line
	 * @param clazz
	 * @return 解析到的对象
	 * *****/
	protected abstract BaseConf analysiConf(String tempString,int line,Class<?> t,BaseConf qe);
	/***
	 * 根据对象名查找制定对象
	 * @param name 关键字
	 * ***/
	//protected abstract BaseConf findConfByName(String name);
	/***
	 * 校验制定配置实体是否存在
	 * @param bConf 待校验的实体
	 * ***/
	//@Override
	public BaseConf findConfByName(String name) {
		if(name==null||name=="")return null;
		selectAllConf();
		for(BaseConf obj:confList){
			if( name.equals(obj.getKey()))
				return obj;
			/*if(((EtcHostsEntity)obj).getName().equals(name))
				return (BaseConf)obj;*/
		}
		// TODO Auto-generated method stub
		return null;
	}
	
	//@Override
	protected boolean isEntityExist(BaseConf bConf) {
		if(bConf==null)return false;
		// TODO Auto-generated method stub
		if(findConfByName(bConf.getKey())!=null)
			return true;
		return false;
	}
	protected abstract List<BaseConf> selectAllConf();
	//protected abstract boolean isEntityExist(BaseConf bConf);
	//protected abstract String[] getElements();
	/***
	 * 校验校验给定行是否是配置标记开始信息
	 * @param line 待校验的行内容
	 * ***/
	protected abstract boolean isConfStart(String line);
	/***
	 * 校验校验给定行是否是配置标记结束信息
	 * @param line 待校验的行内容
	 * ***/
	protected abstract boolean isConfEnd(String line);
	//protected abstract protected boolean isConfStart(String line)
	//protected abstract long getLastModified();
	//protected abstract void setLastModified(long modified);
	//protected abstract void clearConfList();
	//protected abstract boolean addToConfList(Object obj);
	//public abstract List<Object> getConfList();
}
